#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define N 20

void SelecPrint(char Map[N][N], HANDLE hBuffer)
{
    //定义 CHAR_INFO 缓冲区（存储字符 + 颜色）
    CHAR_INFO charBuffer[N + 2][2*N + 2];

    //填充 CHAR_INFO 缓冲区
    //颜色内容：边框：绿色
    //          背景：白色
    //          蛇：黄色
    //          食物：红色
    //上边界
	for(int i = 0; i < 2*N+2; i++)
	{
		charBuffer[0][i].Char.AsciiChar = '-';
		charBuffer[0][i].Attributes = FOREGROUND_GREEN;
		
	}
	//地图内容
    for (int i = 0; i < N; i++)
	{
        //左边界
        charBuffer[i+1][0].Char.AsciiChar = '|';
        charBuffer[i+1][0].Attributes = FOREGROUND_GREEN;
		
        //地图内容
        for(int j = 0; j < N; j++)
		{
            charBuffer[i+1][2*j+1].Char.AsciiChar = Map[i][j];
            charBuffer[i+1][2*j+1].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | 
			                                    BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
            charBuffer[i+1][2*j+2].Char.AsciiChar = ' ';
            charBuffer[i+1][2*j+2].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
			                                    BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
        }
        //最上端横幅
        char Str[30];
        if(i == 4)
		{
			sprintf(Str, "Greedy****  ");
			for(int j = N/2 + 4, k = 0; j <= N/2 + 15; j++)
			{
				charBuffer[i][j].Char.AsciiChar = Str[k++];
				if(Str[k-1] == '*')
					charBuffer[i][j].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | 
												  BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
				else
					charBuffer[i][j].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
			}
		}
		if(i == 5)
		{
			sprintf(Str, "  *****Sn@ke");
			for(int j = N/2 + 4, k = 0; j <= N/2 + 15; j++)
			{
				charBuffer[i][j].Char.AsciiChar = Str[k++];
				if(Str[k-1] == '*' ||Str[k-1] == '@')
					charBuffer[i][j].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | 
												  BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
				else
					charBuffer[i][j].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
			}
		}
		if(i == 6)
		{
			sprintf(Str, " **         ");
			for(int j = N/2 + 4, k = 0; j <= N/2 + 15; j++)
			{
				charBuffer[i][j].Char.AsciiChar = Str[k++];
				if(Str[k-1] == '*')
					charBuffer[i][j].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | 
												  BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
				else
					charBuffer[i][j].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
			}
		}
		charBuffer[7][23].Char.AsciiChar = 'O';
		charBuffer[7][23].Attributes = FOREGROUND_RED | 
									  BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
        //选择1
        if(i == 9)
		{
			sprintf(Str, "1.Start");
			for(int j = N/2 + 2, k = 0; j <= N/2 + 8; j++)
			{
				charBuffer[i][j].Char.AsciiChar = Str[k++];
				charBuffer[i][j].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
			}
		}
        //选择2
        if(i == 10)
		{
			sprintf(Str, "2.Highest Score");
			for(int j = N/2 + 2, k = 0; j <= N/2 + 16; j++)
			{
				charBuffer[i][j].Char.AsciiChar = Str[k++];
				charBuffer[i][j].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
			}
		}
        //选择3
        if(i == 11)
		{
			sprintf(Str, "3.Help");
			for(int j = N/2 + 2, k = 0; j <= N/2 + 7; j++)
			{
				charBuffer[i][j].Char.AsciiChar = Str[k++];
				charBuffer[i][j].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
			}
		}
        //选择4
        if(i == 12)
		{
			sprintf(Str, "4.Exit");
			for(int j = N/2 + 2, k = 0; j <= N/2 + 7; j++)
			{
				charBuffer[i][j].Char.AsciiChar = Str[k++];
				charBuffer[i][j].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
			}
		}
        //提示
        if(i == 15)
		{
			sprintf(Str, "Enter a number for option!");
			for(int j = 9, k = 0; j <= 34; j++)
			{
				charBuffer[i][j].Char.AsciiChar = Str[k++];
				charBuffer[i][j].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
			}
		}

        //右边界
        charBuffer[i+1][2*N+1].Char.AsciiChar = '|';
		charBuffer[i+1][2*N+1].Attributes = FOREGROUND_GREEN;
    }
    //下边界
	for(int i = 0; i < 2*N+2; i++)
	{
		charBuffer[N+1][i].Char.AsciiChar = '-';
		charBuffer[N+1][i].Attributes = FOREGROUND_GREEN;
	}

    COORD bufferSize = {2*N + 2, N + 2};    //定义写入区域
    COORD bufferCoord = {0, 0};      //从 CHAR_INFO 缓冲区的 (0,0) 开始读取
    SMALL_RECT writeRegion = {0, 0, 2*N + 1, N + 1};   //控制台写入区域

    //使用双缓冲一次性写入字符和颜色
    WriteConsoleOutput(
        hBuffer,    //控制台的屏幕缓冲区（直接输出的缓冲区）
        (CHAR_INFO*)charBuffer,     // CHAR_INFO 缓冲区（预先准备的写入了字符和颜色的缓冲区）
        bufferSize,    //写入的区域
        bufferCoord,    //读取起始点
        &writeRegion    //控制台写入区域
    );

    //重置光标
    SetConsoleCursorPosition(hBuffer, (COORD){0, 0});
}

void SelecLogic(HANDLE hBuffer)
{
    //定义并清洗地图
    char Map[N][N];
    for(int i = 0; i < N; i++)
	{
		for(int j = 0; j < N; j++)
		{
			Map[i][j] = ' ';
		}
	}

    //打印地图
	SelecPrint(Map, hBuffer);
	Sleep(500);
    while (1)
	{
        //检测键盘录入
		if(GetAsyncKeyState('1') & 0x8000)
		{
			break;
		}
		if(GetAsyncKeyState('2') & 0x8000)
		{
			break;
		}
		if(GetAsyncKeyState('3') & 0x8000)
		{
			break;
		}
		if(GetAsyncKeyState('4') & 0x8000)
		{
			break;
		}
        SelecPrint(Map, hBuffer);
        Sleep(100);
    }
}

int main()
{
	//定义双缓冲的句柄
	HANDLE hBuffer = CreateConsoleScreenBuffer(
	    GENERIC_READ | GENERIC_WRITE,	//缓冲区设置为可读（输出）可写（改变状态）
	    FILE_SHARE_READ | FILE_SHARE_WRITE,
	    NULL,	//默认安全属性
	    CONSOLE_TEXTMODE_BUFFER,	//应为程序由字符呈现，故采用文本模式的缓冲区
	    NULL	//无模板
	);
	SetConsoleActiveScreenBuffer(hBuffer); 		//设置为活动缓冲区
	
	SelecLogic(hBuffer);
	
    //释放资源
    SetConsoleActiveScreenBuffer(GetStdHandle(STD_OUTPUT_HANDLE));
	CloseHandle(hBuffer);
    printf("程序结束\n");
    return 0;
}
